/******************************************************************************
 * This file is part of libemb.
 *
 * libemb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libemb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libemb.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project: Embedme
 * Author : FergusZeng
 * Email  : cblock@126.com
 * git	  : https://gitee.com/newgolo/embedme.git
 * Copyright 2014~2020 @ ShenZhen ,China
*******************************************************************************/
#ifndef __EVIO_H__
#define __EVIO_H__

#include "ev++.h"
#include "libemb/BaseType.h"
#include "libemb/Thread.h"

#define EV_USE_STDEXCEPT 0
namespace libembx{

enum EVIO_TYPE_E
{
	EVIO_TYPE_IO=0,
	EVIO_TYPE_TIMER,
	EVIO_TYPE_SIGNAL
};

enum EVIO_EVT_E
{
	EVIO_EVT_READ=EV_READ,
	EVIO_EVT_WRITE=EV_WRITE,
	EVIO_EVT_TIMEOUT=EV_TIMER,
	EVIO_EVT_SIGNAL=EV_SIGNAL,
};

class EVWatcher{
DECL_CLASSNAME(EVWatcher)
public:
	EVWatcher();
	virtual ~EVWatcher();
	int type();
protected:
	int m_type;
};

class EVIO:public EVWatcher{
DECL_CLASSNAME(EVIO)
public:
	EVIO();
	virtual ~EVIO();
	bool setEvent(int fd, int evioEvt);
	virtual void onEvent(int evioEvt)=0;
private:
	void evCallBack(ev::io& evio, int revents);
private:
	friend class EVLoop;
	ev::io m_evio;
	int m_fd;
	int m_evt;
};


class EVTimer:public EVWatcher{
DECL_CLASSNAME(EVTimer)
public:
	EVTimer();
	virtual ~EVTimer();
	bool setTimer(int msTimeout, bool repeat=false);
	virtual void onTimeout()=0;
private:
	void evCallBack(ev::timer& evtimer, int revents);
private:
	friend class EVLoop;
	ev::timer m_evtimer;
};

class EVSignal:public EVWatcher{
DECL_CLASSNAME(EVSignal)
public:
	EVSignal();
	virtual ~EVSignal();
	bool setSignal(int signum);
	virtual void onSignal()=0;
private:
	void evCallBack(ev::sig& evsignal, int revents);
private:
	friend class EVLoop;
	ev::sig m_evsig;
};

class EVLoop:public libemb::Runnable{
DECL_CLASSNAME(EVLoop)
public:
	EVLoop();
	~EVLoop();
	bool initialize();
	bool addWatcher(EVWatcher* watcher);
	bool removeWatcher(EVWatcher* watcher);
private:
	void run(libemb::Thread& thread);
private:
	std::unique_ptr<ev::dynamic_loop> m_dynLoop;
};


}

#endif
